package com.lsh.ofc.worker.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dangdang.ddframe.job.api.JobExecutionMultipleShardingContext;
import com.dangdang.ddframe.job.plugin.job.type.simple.AbstractSimpleElasticJob;
import com.lsh.base.common.exception.BusinessException;
import com.lsh.base.common.utils.CollectionUtils;
import com.lsh.ofc.core.constant.Constants;
import com.lsh.ofc.core.entity.OfcOrderHead;
import com.lsh.ofc.core.entity.OfcSoDetail;
import com.lsh.ofc.core.entity.OfcSoHead;
import com.lsh.ofc.core.proxy.service.WumartBasicService;
import com.lsh.ofc.core.redis.RedisTemplate;
import com.lsh.ofc.core.service.OfcOrderService;
import com.lsh.ofc.core.service.OfcSoService;
import com.lsh.ofc.core.util.IdGenerator;
import com.lsh.ofc.proxy.context.WumartBasicContext;
import com.lsh.ofc.proxy.model.CreateWgSoRespHead;
import com.lsh.ofc.proxy.model.CreateWgStoReqDetail;
import com.lsh.ofc.proxy.model.CreateWgStoReqHead;
import com.lsh.ofc.proxy.service.WgServiceProxy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Project Name: lsh-ofc
 * @author fuhao
 * Date: 18/6/19
 * Time: 18/6/19.
 * 北京链商电子商务有限公司
 * Package name:com.lsh.ofc.worker.task.
 * desc:定时任务，汇总sto
 */
@Slf4j
@Component
public class SummarySoJob extends AbstractSimpleElasticJob {

    @Autowired
    private OfcSoService ofcSoService;

    @Autowired
    private OfcOrderService ofcOrderService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private WumartBasicService wumartBasicService;

    @Override
    public void process(JobExecutionMultipleShardingContext jobContext) {
        // 默认100
        try {
            log.info("ofc_task sto task create 开始...");
            long start = System.currentTimeMillis();
            List<OfcSoHead> orders = new ArrayList<>();
            Map<String,String> params  = this.getCollectOrder(jobContext, orders);
            if(CollectionUtils.isEmpty(orders)){
                return;
            }
            String stoKey = params.get("orderStoKey");
            //订单信息
            Map<Long, OfcOrderHead> orderCode2orderCodeMap = new HashMap<>(orders.size() * 2);
            OfcOrderHead filer = new OfcOrderHead();
            List<String> redisOrderCodeList = new ArrayList<>();
            Map<String,BigDecimal> skuQtyMap = new HashMap<>();
            Map<String,Long> skuItemMap = new HashMap<>();
            Long venderId = null;

            for (OfcSoHead order : orders) {
                //获取订单信息
                OfcOrderHead ofcOrderHead ;
                Long orderCode = order.getOrderCode();
                if(orderCode2orderCodeMap.containsKey(orderCode)){
                    ofcOrderHead = orderCode2orderCodeMap.get(orderCode);
                }else {
                    filer.setOrderCode(orderCode);
                    ofcOrderHead = ofcOrderService.findOne(filer,false);
                    orderCode2orderCodeMap.put(orderCode,ofcOrderHead);
                }
                venderId = ofcOrderHead.getVenderId();
                //去重已经汇总的sto key的组成region_code，supplier_id，supplier_dc，supplier_org，supplier_group,时间,code
                String redisOrderCode = getFCode(ofcOrderHead);
                String orderStoKey = stoKey +":"+redisOrderCode;
                if (redisTemplate.exists(orderStoKey)) {
                    continue;
                }
                redisOrderCodeList.add(redisOrderCode);

                List<OfcSoDetail> ofcSoDetails = order.getDetails();

                for(OfcSoDetail ofcSoDetail:ofcSoDetails){
                    BigDecimal qty = BigDecimal.ZERO;
                    if(skuQtyMap.containsKey(ofcSoDetail.getSkuSupplyCode())){
                        qty = skuQtyMap.get(ofcSoDetail.getSkuSupplyCode());
                    }
                    qty = qty.add(ofcSoDetail.getSkuOrderQty());
                    skuQtyMap.put(ofcSoDetail.getSkuSupplyCode(),qty);
                    skuItemMap.put(ofcSoDetail.getSkuSupplyCode(),ofcSoDetail.getSkuCode());
                }
            }

            List<CreateWgStoReqDetail> items = new ArrayList<>();
            Integer lineNo = 10;
            for(String code:skuQtyMap.keySet()){
                CreateWgStoReqDetail createWgStoReqDetail = new CreateWgStoReqDetail();
                createWgStoReqDetail.setGoodsId(code);
                createWgStoReqDetail.setQty(skuQtyMap.get(code));
                createWgStoReqDetail.setLineNo(lineNo.toString());
                createWgStoReqDetail.setUnit("EA");
                createWgStoReqDetail.setSkuCode(skuItemMap.get(code));
                lineNo = lineNo + 10;
                items.add(createWgStoReqDetail);
            }
            params.put("venderId",venderId.toString());
            this.dealSto(params,items,redisOrderCodeList);

            long end = System.currentTimeMillis();
            log.info("ofc_task sto task create 完成... 处理行数：" + orders.size() + "，耗时：" + (end - start));
        } catch (BusinessException e) {
            log.error("ofc_task sto task create 异常... " + e.getMessage(), e);
        }
    }

    private void dealSto(Map<String,String> params ,List<CreateWgStoReqDetail> items,List<String> redisOrderCodeList) throws BusinessException{
        if (CollectionUtils.isEmpty(items)) {
            return;
        }
        String toDc = params.get("toDc");
        String ownerId = params.get("ownerId");
        String wgPath = params.get("path");
        String fromDc = params.get("fromDc");
        String stoKey = params.get("orderStoKey");
        String venderId = params.get("venderId");
        String summaryType = params.get("summaryType");
        CreateWgStoReqHead createStoReq = new CreateWgStoReqHead();
        createStoReq.setSendWarehouseCode(fromDc);
        createStoReq.setMisVenderId(Long.valueOf(venderId));
        createStoReq.setReceiveWarehouseCode(toDc);
        createStoReq.setOwnerId(ownerId);
        createStoReq.setOrderId(IdGenerator.getId());
        createStoReq.setItems(items);
        createStoReq.setWgPath(wgPath);
        createStoReq.setSummaryType(summaryType);
        try{
            //汇总信息存redis，再设置一个job专门推送信息，如果成功，则删除，否则重新推送

            String orderKey = MessageFormat.format(Constants.OFC_STO_PUST_PSI_STATUS,createStoReq.getOrderId());

            redisTemplate.set(orderKey, JSON.toJSONString(createStoReq));

            redisTemplate.sadd(Constants.OFC_STO_PUST_PSI_ORDERS,orderKey);

//            CreateWgSoRespHead createSoResp = wgServiceProxy.createSto(createStoReq, wgPath);
//
//            logger.info("*****CreateWgStoRespHead createSoResp is " + JSON.toJSONString(createSoResp));
//
//            //推送成功，给redis存入数据(时间)
//
//            SimpleDateFormat spdf = new SimpleDateFormat("yyyy-MM-dd");
//
//            String orderStoKey = MessageFormat.format(Constants.OFC_STO_PUST_STATUS, fromDc, toDc,spdf.format(new Date()));
//            //一天的时间有效期
//            redisTemplate.set(orderStoKey, createSoResp.getSoId(),60*60*24);
        }catch (Exception e){
            throw e;
        }
        log.info("汇总单汇总完成，汇总单号:"+createStoReq.getOrderId());
        if(summaryType.equals(Constants.TYPE_SUMMARY_PSI_STO)) {
            for (String orderCode : redisOrderCodeList) {
                this.setRedisDealFlag(stoKey, orderCode);
            }
        }

    }

    /**
     * 查询需要汇总的订单
     * @param jobContext   任务上线文
     * @param orders       需要汇总的订单列表
     * @return             汇总sto指定大小
     */
    private Map<String,String> getCollectOrder(JobExecutionMultipleShardingContext jobContext, List<OfcSoHead> orders) {
        Map<String,String> params = new HashMap<>();
        String exeArgs = jobContext.getJobParameter();
        log.info("create sto task params:"+exeArgs);
        if(StringUtils.isBlank(exeArgs)){
            //无配置信息，不汇总
            return null;
        }
        String[] exeTimeArr = exeArgs.split(";");
        //开始时间:结束时间:调出仓库:调入仓库:用户组:区域:货主:机构
        String startTimePoint = exeTimeArr[0];
        String endTimePoint = exeTimeArr[1];
        String fromDc = exeTimeArr[2];
        String toDc = exeTimeArr[3];
        String group = exeTimeArr[4];
        Integer regionCode = Integer.valueOf(exeTimeArr[5]);
        Integer supplierOrg = Integer.valueOf(exeTimeArr[6]);
        Integer supplierId = Integer.valueOf(exeTimeArr[7]);
        String summaryType = exeTimeArr.length>8 ? exeTimeArr[8] : Constants.TYPE_SUMMARY_PSI_STO;
        String[] startTimePointArr = startTimePoint.split(":");
        String[] endTimePointArr = endTimePoint.split(":");
        String todayStr = new SimpleDateFormat("yyyyMM").format(new Date());
        Date nowDate = new Date();
        Integer startTime = this.getStartTime(nowDate, Integer.parseInt(startTimePointArr[0]), Integer.parseInt(startTimePointArr[1]));
        Integer endTime = this.getEndTime(nowDate, Integer.parseInt(endTimePointArr[0]), Integer.parseInt(endTimePointArr[1]));

        List<OfcSoHead> ordersDb = ofcSoService.findListFilterByTime(startTime, endTime, group, fromDc, regionCode, supplierOrg, supplierId);
        orders.addAll(ordersDb);
        log.info("[sto 汇总时间] 统计范围 {} - {} ,size = " + orders.size(), startTime, endTime);

        String ownerId;
        if(summaryType.equals(Constants.TYPE_SUMMARY_PSI_STO)) {
            ownerId = this.wumartBasicService.getOwnerId(WumartBasicContext.buildContext(regionCode, fromDc, supplierOrg, supplierId, group));
        }else {
            ownerId = this.wumartBasicService.getScOwnerId(WumartBasicContext.buildContext(regionCode, fromDc, supplierOrg, supplierId, group));
        }
        String wgPath = this.wumartBasicService.getWmsPath(WumartBasicContext.buildContext(regionCode, fromDc, supplierOrg, supplierId,group));


        String orderStoKey = MessageFormat.format(Constants.OFC_MERGE_STO_ORDER, regionCode, supplierId, fromDc, supplierOrg, todayStr);
        params.put("toDc", toDc);
        params.put("ownerId", ownerId);
        params.put("fromDc",fromDc);
        params.put("path",wgPath);
        params.put("orderStoKey",orderStoKey);
        params.put("summaryType",summaryType.toString());
        return params;

    }


    /**
     * 设置汇总redis标记
     *
     * @param orderCode 订单号
     */
    private void setRedisDealFlag(String key,String orderCode) {

        redisTemplate.set(key+ ":" + orderCode, orderCode, 386400);
    }


    /**
     * 时间戳
     *
     * @param date        日期
     * @param hourPoint   小时
     * @param minutePoint 分钟
     * @return 时间戳
     */
    private Integer getStartTime(Date date, int hourPoint, int minutePoint) {

        return (int) TimeUnit.MILLISECONDS.toSeconds(this.getPreviousDayAndHourMorning(date, hourPoint, minutePoint).getTime());
    }

    /**
     * 统计结束时间
     *
     * @param hourPoint 时间点
     * @return 时间戳
     */
    private Integer getEndTime(Date date, int hourPoint, int minutePoint) {

        return (int) TimeUnit.MILLISECONDS.toSeconds(this.getDayHourMorning(date, hourPoint, minutePoint).getTime());
    }

    private Date getPreviousDayAndHourMorning(Date date, int hourPoint, int minutePoint) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, hourPoint);
        calendar.set(Calendar.MINUTE, minutePoint);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.DATE, -1);

        return calendar.getTime();
    }

    private Date getDayHourMorning(Date date, int hourPoint, int minutePoint) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, hourPoint);
        calendar.set(Calendar.MINUTE, minutePoint);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }
    private String getFCode(OfcOrderHead ofcOrderHead){
        String parentOrderCode = JSONObject.parseObject(ofcOrderHead.getExt()).getString("parent_order_code");
        if(parentOrderCode.equals("0")){
            return ofcOrderHead.getOrderCode().toString();
        }else {
            return parentOrderCode;
        }
    }
}
